package learm.pers.studysonarqube.codescanning.service.impl;

import learm.pers.studysonarqube.codescanning.service.ScanningService;
import learm.pers.studysonarqube.codescanning.vo.SonarIssuesMusterVo;
import learm.pers.studysonarqube.codescanning.vo.SonarPagingVo;
import learm.pers.studysonarqube.codescanning.vo.SonarProjectMeasuresVo;
import learm.pers.studysonarqube.codescanning.vo.SonarProjectVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: ScanningServiceImpl
 * @Description:
 * @Author: fangqing
 * @Date: 2021/7/27
 */
@Service
public class ScanningServiceImpl implements ScanningService {

    private static Logger logger = LoggerFactory.getLogger(ScanningServiceImpl.class);

    @Resource
    RestTemplate restTemplate;

    @Value("${sonarqube.url}")
    private String SQ_URL;

    @Value("${sonarqube.username}")
    private String SQ_USERNAME;

    @Value("${sonarqube.password}")
    private String SQ_PASSWORD;

    /**
     * 设置公共的请求头
     * @param body
     * @return
     */
    public HttpEntity<String> responseEntity(String body){
        try{
            String encoding = "Basic " + new String(Base64.getEncoder().encode((SQ_USERNAME+":"+SQ_PASSWORD).getBytes("UTF-8")));
            HttpHeaders requestHeaders = new HttpHeaders();
            //添加认证的请求头
            requestHeaders.add("Authorization", encoding);
            HttpEntity<String> requestEntity = new HttpEntity<String>(body, requestHeaders);
            return requestEntity;
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取 SonarQube扫描的项目(组件)
     * @param sonarPagingVo  分页
     * @param projectsKey  项目的key
     * @return
     */
    @Override
    public SonarProjectVo findProjects(SonarPagingVo sonarPagingVo, String projectsKey) {
        try{
            String url = SQ_URL+"/api/projects/search?p={p}&ps={ps}";
            Map<String, Object> uriVariables = new HashMap<>();
            uriVariables.put("p", sonarPagingVo.getPageIndex());
            uriVariables.put("ps", sonarPagingVo.getPageSize());
            if(!"".equals(projectsKey) && projectsKey!=null){
                url+="&projects={projects}";
                uriVariables.put("projects", projectsKey);
            }
            HttpEntity<String> requestEntity = responseEntity(null);

            ParameterizedTypeReference<SonarProjectVo> responseType = new ParameterizedTypeReference<SonarProjectVo>() {};
            ResponseEntity<SonarProjectVo> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, responseType,uriVariables);
            if (HttpStatus.OK == responseEntity.getStatusCode()) {
                return responseEntity.getBody();
            }
            logger.info(String.valueOf(responseEntity.getBody()));
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return null;
    }

    /**
     * 获取 SonarQube扫描的指标措施
     * @param projectsKey 项目的key
     * @return
     */
    @Override
    public SonarProjectMeasuresVo findMeasures(String projectsKey) {
        try{
            //问题数/缺陷/漏洞/代码异常/覆盖范围/重复行/重复块/圈复杂度/认知复杂性/非注释代码行
            String Keys="violations,bugs,vulnerabilities,code_smells,coverage,duplicated_lines,duplicated_blocks,complexity,cognitive_complexity,ncloc";

            String url = SQ_URL+"/api/measures/component?component=" + projectsKey + "&metricKeys="+ Keys;
            HttpEntity<String> requestEntity = responseEntity(null);

            ParameterizedTypeReference<SonarProjectMeasuresVo> responseType = new ParameterizedTypeReference<SonarProjectMeasuresVo>() {};
            ResponseEntity<SonarProjectMeasuresVo> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, responseType);
            if (HttpStatus.OK == responseEntity.getStatusCode()) {
                return responseEntity.getBody();
            }
            logger.info(String.valueOf(responseEntity.getBody()));
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return null;
    }
    /**
     * 获取问题集合
     * @param sonarPagingVo 分页
     * @param projectsKey 项目的key
     * @param types 问题类型（BUG,VULNERABILITY,CODE_SMELL  == 缺陷,漏洞,代码异常）
     * @return
     */
    @Override
    public SonarIssuesMusterVo findIssues(SonarPagingVo sonarPagingVo, String projectsKey, String types) {
        try{
            String url = SQ_URL+"/api/issues/search?p={p}&ps={ps}";
            Map<String, Object> uriVariables = new HashMap<>();
            uriVariables.put("p", sonarPagingVo.getPageIndex());
            uriVariables.put("ps", sonarPagingVo.getPageSize());
            if(!"".equals(types) && types != null){
                url+="&types={types}";
                uriVariables.put("types", types);
            }
            if(!"".equals(projectsKey) && projectsKey != null){
                url+="&componentKeys={componentKeys}";
                uriVariables.put("componentKeys", projectsKey);
            }

            HttpEntity<String> requestEntity = responseEntity(null);

            ParameterizedTypeReference<SonarIssuesMusterVo> responseType = new ParameterizedTypeReference<SonarIssuesMusterVo>() {};
            ResponseEntity<SonarIssuesMusterVo> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, responseType, uriVariables);
            if (HttpStatus.OK == responseEntity.getStatusCode()) {
                return responseEntity.getBody();
            }
            logger.info(String.valueOf(responseEntity.getBody()));
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return null;
    }
}
